﻿using System;
using JetBrains.Annotations;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.Xaml.Impl.Resolve;

namespace GammaJul.ReSharper.GammaXaml.Psi.Xaml {

	/// <summary>
	/// Contains extension methods related to <see cref="IXamlTypeCache"/>.
	/// </summary>
	public static class XamlTypeCacheExtensions {
		private const string AssemblyWindowsBase = "WindowsBase";
		private const string AssemblySystemWindows = "System.Windows";
		private const string AssemblyPresentationFramework = "PresentationFramework";

		/// <summary>
		/// Gets a type representing DependencyPropertyKey from a <see cref="IXamlTypeCache"/>.
		/// </summary>
		/// <param name="xamlTypeCache">A <see cref="IXamlTypeCache"/> instance.</param>
		/// <returns>A <see cref="IDeclaredType"/>, or <c>null</c>.</returns>
		[NotNull]
		public static IDeclaredType DependencyPropertyKey([NotNull] this IXamlTypeCache xamlTypeCache) {
			return xamlTypeCache.GetType("System.Windows.DependencyPropertyKey", new[] { AssemblyWindowsBase });
		}

		/// <summary>
		/// Gets a type representing PropertyMetadata from a <see cref="IXamlTypeCache"/>.
		/// </summary>
		/// <param name="xamlTypeCache">A <see cref="IXamlTypeCache"/> instance.</param>
		/// <returns>A <see cref="IDeclaredType"/>, or <c>null</c>.</returns>
		[NotNull]
		public static IDeclaredType PropertyMetadata([NotNull] this IXamlTypeCache xamlTypeCache) {
			return xamlTypeCache.GetType("System.Windows.PropertyMetadata", new[] { AssemblyWindowsBase, AssemblySystemWindows });
		}

		/// <summary>
		/// Gets a type representing TemplateBindingExtension from a <see cref="IXamlTypeCache"/>.
		/// </summary>
		/// <param name="xamlTypeCache">A <see cref="IXamlTypeCache"/> instance.</param>
		/// <returns>A <see cref="IDeclaredType"/>, or <c>null</c>.</returns>
		[NotNull]
		public static IDeclaredType TemplateBindingExtension([NotNull] this IXamlTypeCache xamlTypeCache) {
			return xamlTypeCache.GetType("System.Windows.TemplateBindingExtension", new[] { AssemblyPresentationFramework });
		}

		/// <summary>
		/// Gets a type representing Grid from a <see cref="IXamlTypeCache"/>.
		/// </summary>
		/// <param name="xamlTypeCache">A <see cref="IXamlTypeCache"/> instance.</param>
		/// <returns>A <see cref="IDeclaredType"/>, or <c>null</c>.</returns>
		[NotNull]
		public static IDeclaredType Grid([NotNull] this IXamlTypeCache xamlTypeCache) {
			return xamlTypeCache.GetType("System.Windows.Controls.Grid", new[] { AssemblyPresentationFramework, AssemblySystemWindows });
		}

		/// <summary>
		/// Gets a type representing RowDefinition from a <see cref="IXamlTypeCache"/>.
		/// </summary>
		/// <param name="xamlTypeCache">A <see cref="IXamlTypeCache"/> instance.</param>
		/// <returns>A <see cref="IDeclaredType"/>, or <c>null</c>.</returns>
		[NotNull]
		public static IDeclaredType RowDefinition([NotNull] this IXamlTypeCache xamlTypeCache) {
			return xamlTypeCache.GetType("System.Windows.Controls.RowDefinition", new[] { AssemblyPresentationFramework, AssemblySystemWindows });
		}

		/// <summary>
		/// Gets a type representing ColumnDefinition from a <see cref="IXamlTypeCache"/>.
		/// </summary>
		/// <param name="xamlTypeCache">A <see cref="IXamlTypeCache"/> instance.</param>
		/// <returns>A <see cref="IDeclaredType"/>, or <c>null</c>.</returns>
		[NotNull]
		public static IDeclaredType ColumnDefinition([NotNull] this IXamlTypeCache xamlTypeCache) {
			return xamlTypeCache.GetType("System.Windows.Controls.ColumnDefinition", new[] { AssemblyPresentationFramework, AssemblySystemWindows });
		}


		/// <summary>
		/// Gets a type representing RowDefinition or ColumnDefinition from a <see cref="IXamlTypeCache"/>.
		/// </summary>
		/// <param name="xamlTypeCache">A <see cref="IXamlTypeCache"/> instance.</param>
		/// <param name="definitionType">The type of grid definition.</param>
		public static IDeclaredType GridDefinition(this IXamlTypeCache xamlTypeCache, GridDefinitionType definitionType) {
			switch (definitionType) {
				case GridDefinitionType.Row:
					return xamlTypeCache.RowDefinition();
				case GridDefinitionType.Column:
					return xamlTypeCache.ColumnDefinition();
				default:
					throw new ArgumentOutOfRangeException("definitionType");
			}
		}

	}

}